package nus.mtech.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import nus.mtech.bill.Account;
import nus.mtech.bill.AccountManager;
import nus.mtech.bill.Bill;
import nus.mtech.bill.BillManager;
import nus.mtech.customer.Complaint;
import nus.mtech.customer.ComplaintManager;
import nus.mtech.customer.Customer;
import nus.mtech.customer.CustomerManager;
import nus.mtech.subscription.Subscription;
import nus.mtech.subscription.SubscriptionManager;
 
/**
 * <p>Title</p>
 * <p>Copyright (c) 2011 NUS ISS.  All rights reserved. </p>
 * @author Jiang Hao Min
 * @version 1.0
 *
 * <p align='left'>
 * <table border='1' width='80%'>
 *   <tr>
 *     <th colspan='4'>Change History</th>
 *   </tr>
 *   <tr>
 *     <td><u>Version</u></td>
 *     <td><u>Name</u></td>
 *     <td><u>Date</u></td>
 *     <td><u>Remarks</u></td>
 *   </tr>
 *   <tr>
 *     <td>1.0</td>
 *     <td>Jiang Hao Min</td>
 *     <td>Mar 24, 2011</td>
 *     <td>Creation of the class.</td>
 *   </tr>
 * </table>
 * </p>
 */

public class ExpDataUtil {
	private final static String FILE_SEP = File.separator;
	private final static String PROJECT_DIR = System.getProperty("user.dir");
	
	public static void saveData() throws IOException{
		String outputPath = PROJECT_DIR + FILE_SEP + "data";

		BackupExistFile(outputPath);
		
		String outputFile = outputPath + FILE_SEP + "SeqNo.dat";
		SaveForSeqNo(outputFile);
		
		outputFile = outputPath + FILE_SEP + "Customer.dat";
		SaveForCustomer(outputFile);
		
		outputFile = outputPath + FILE_SEP + "CustomerInfoForQuery.txt";
		SaveForCustomerQueryInfo(outputFile);
		
		outputFile = outputPath + FILE_SEP + "CustomerAccount.dat";
		SaveForCustomerAccount(outputFile);
		
		outputFile = outputPath + FILE_SEP + "Complaint.dat";
		SaveForComplaint(outputFile);
		
		outputFile = outputPath + FILE_SEP + "Subscription.dat";
		SaveForSubscription(outputFile);
		
		outputFile = outputPath + FILE_SEP + "Bill.dat";
		SaveForBill(outputFile);
	}
	
	private static void SaveForSeqNo(String outputFile) throws IOException{
		OutputStream os = null;
		ObjectOutputStream oos = null;
		
		
		try{
			os = new FileOutputStream(outputFile);
			oos = new ObjectOutputStream(os);
			
			int customerId = CustomerManager.getCustomerManagerInstance().getCustomerId();
			int customerAccountId = Integer.parseInt(AccountManager.getInstance().getAccountUID());
			int complaintId = ComplaintManager.getComplaintManagerInstance().getComplaintId();
			int billId = BillManager.getBillManagerInstance().getBillId();
			
			System.out.println("Final Saving: customerId=" + customerId + ", complaintId=" + complaintId + ", billId=" + billId + ", accountId=" + customerAccountId);
			
			oos.writeInt(customerId);
			oos.writeInt(customerAccountId);
			oos.writeInt(complaintId);
			oos.writeInt(billId);
		}finally{
			if(null != oos){
				oos.close();
			}
			if(null != os){
				os.close();
			}
		}
	}
	
	private static void SaveForCustomer(String outputFile) throws IOException{
		OutputStream os = null;
		ObjectOutputStream oos = null;
		
		HashMap<String, Customer> map = CustomerManager.getCustomerManagerInstance().getCustomerMap();
		
		if(null != map && 0 < map.size()){
			try{
				os = new FileOutputStream(outputFile);
				oos = new ObjectOutputStream(os);
				
				oos.writeObject(map);
			}finally{
				if(null != oos){
					oos.close();
				}
				if(null != os){
					os.close();
				}
			}
		}
	}
	
	private static void SaveForCustomerQueryInfo(String outputFile) throws IOException{
		FileWriter fw = null;
        PrintWriter outFile = null;
        
        List<Customer> list = CustomerManager.getCustomerManagerInstance().getAllCustomers();
		
        if(null != list && 0 < list.size()){
        	Collections.sort(list, new Comparator<Customer>(){
        		public int compare(Customer a, Customer b){
        			return a.getCustName().compareToIgnoreCase(b.getCustName());
        		}
        	});
        	
	        try{
				fw = new FileWriter(outputFile, false);
				outFile = new PrintWriter(fw);
				
				String str = "NRIC\tName";
				outFile.println(str);
				
				for(Customer customer:list){
					str = customer.getCustNRIC() + "\t" + customer.getCustName();
					outFile.println(str);
				}
	        }finally{
	        	if(null != outFile){
	        		outFile.close();
	        	}
	        	if(null != fw){
	        		fw.close();
	        	}
	        }
        }
	}
	
	private static void SaveForCustomerAccount(String outputFile) throws IOException{
		OutputStream os = null;
		ObjectOutputStream oos = null;
		
		HashMap<String, Account> map = AccountManager.getInstance().getAccountMap();
		
		if(null != map && 0 < map.size()){
			try{
				os = new FileOutputStream(outputFile);
				oos = new ObjectOutputStream(os);
				
				oos.writeObject(map);
			}finally{
				if(null != oos){
					oos.close();
				}
				if(null != os){
					os.close();
				}
			}
		}
	}
	
	private static void SaveForComplaint(String outputFile) throws IOException{
		OutputStream os = null;
		ObjectOutputStream oos = null;
		
		Map<String, ArrayList<Complaint>> map = ComplaintManager.getComplaintManagerInstance().getComplaintMap();
		
		if(null != map && 0 < map.size()){
			try{
				os = new FileOutputStream(outputFile);
				oos = new ObjectOutputStream(os);
				
				oos.writeObject(map);
			}finally{
				if(null != oos){
					oos.close();
				}
				if(null != os){
					os.close();
				}
			}
		}
	}
	
	private static void SaveForSubscription(String outputFile) throws IOException{
		OutputStream os = null;
		ObjectOutputStream oos = null;
		
		HashMap<String, ArrayList<Subscription>> map = SubscriptionManager.getSubscriptionManagerInstance().getMapOfSubscriptions();
		
		if(null != map && 0 < map.size()){
			try{
				os = new FileOutputStream(outputFile);
				oos = new ObjectOutputStream(os);
				
				oos.writeObject(map);
			}finally{
				if(null != oos){
					oos.close();
				}
				if(null != os){
					os.close();
				}
			}
		}
	}
	
	private static void SaveForBill(String outputFile) throws IOException{
		OutputStream os = null;
		ObjectOutputStream oos = null;
		
		HashMap<String, ArrayList<Bill>> map = BillManager.getBillManagerInstance().getMapOfBills();
		HashMap<String, Date> flagMap = BillManager.getBillManagerInstance().getMonthlyBillFlagMap();
		
		if(null != map && 0 < map.size()){
			try{
				os = new FileOutputStream(outputFile);
				oos = new ObjectOutputStream(os);
				
				oos.writeObject(map);
				oos.writeObject(flagMap);
			}finally{
				if(null != oos){
					oos.close();
				}
				if(null != os){
					os.close();
				}
			}
		}
	}
	
	private static void BackupExistFile(String outputPath) throws IOException{
		String timestamp = DateUtil.formatDate(new Date(), "yyyyMMdd_HHmmss");
		String bakupPath = outputPath + FILE_SEP + "backup";
		File folder = new File(bakupPath);
		if(!folder.exists()){
        	folder.mkdir();
        }
		bakupPath += FILE_SEP + timestamp;
		folder = new File(bakupPath);
        if(!folder.exists()){
        	folder.mkdir();
        }
		
		File dir = new File(outputPath);
        String[] fileNames = dir.list();
        
        for(int i = 0;i < fileNames.length;i++){
        	String dataFile = outputPath + FILE_SEP + fileNames[i];
			File f = new File(dataFile);
        	
			if(f.isFile()){
	        	int n = fileNames[i].lastIndexOf(".");
	        	if(n != -1){
	        		String str = fileNames[i].substring(n + 1);
	        		if("properties".equalsIgnoreCase(str) || "bak".equalsIgnoreCase(str) || 
	        			"Call.txt".equalsIgnoreCase(fileNames[i]) || "account.txt".equalsIgnoreCase(fileNames[i]) ||
	        			"rates.txt".equalsIgnoreCase(fileNames[i])){
	        			continue;
	        		}
	        	}
	        	
	        	String bakupFile = bakupPath + FILE_SEP + fileNames[i] + ".bak";
	        	
				copy(f, new File(bakupFile));
				f.delete();
			}
        }
	}
	
	private static void copy(File src, File dst) throws IOException	{
		try	{
			InputStream in = new FileInputStream(src);
			OutputStream out = new FileOutputStream(dst);
		
			// Transfer byte from in to out
			byte[] buf = new byte[(int)src.length()];
			int len;
		
			while ((len = in.read(buf)) > 0){
				out.write(buf, 0, len);
			}
			in.close();
			out.close();
		}
		catch (IOException e){
			throw e;
		}
	}

}
